package com.elite.groovy.callback

import com.elite.groovy.davco.clink.ClinkUtils
import com.elite.groovy.kh.KHDBConfig
import com.elite.groovy.kh.KHUtil
import com.elite.groovy.util.EliteBean
import com.elite.groovy.util.Util
import com.fasterxml.jackson.core.JsonProcessingException
import com.tinet.clink.core.exceptions.ClientException
import com.tinet.clink.core.exceptions.ServerException
import net.sf.json.JSONArray
import net.sf.json.JSONObject
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.jdbc.core.JdbcTemplate

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import java.text.SimpleDateFormat

/**
 * @projectName: Groovy
 * @package: com.elite.groovy.callback
 * @className: apiClinkMonitorQueue
 * @description: 天润队列监控
 * @author: LiJT
 * @date: 2023-10-27 11:13
 * @version: 1.0
 */
public class apiClinkMonitorQueue implements ServiceBackInvoke {
    private static final Logger log = LoggerFactory.getLogger(apiClinkMonitorQueue.class);

    public String doCallBack(EliteBean eliteBean, HttpServletRequest request, HttpServletResponse response) {
        SimpleDateFormat sdateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 获取数据源
        JdbcTemplate jt = new JdbcTemplate(eliteBean.getDataSource());
        // 获取当前时间
        Date date = new Date();
        String Update_Time = sdateFormat.format(date);

        // 获取所有Header
        Map<String, String> mapHeader = new HashMap<String, String>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            // log.debug("Call Header-" + key + ":" + value);

            mapHeader.put(key, value);
        }

        // 封装调用头Heads
        Map<String, String> headMap = new HashMap<String, String>();
        headMap.put("Content-Type", "application/json");

        // 系统接入-GET
        String getPath = "/cc/queue_status?";

        Map<String, String> queryParams = new HashMap<String, String>();
        String[] Qnos = KHDBConfig.getParamConfig(eliteBean, "TR-AQU").split(";");
        for (int i = 0; i < Qnos.length; i++) {
            queryParams.put("qnos[" + i + "]", Qnos[i]);
        }

        String doGETRes = ClinkUtils.doClinkCall("GET", getPath, queryParams, headMap, null);
        // log.debug("系统接入 doGETRes:" + doGETRes);

        try {
            JSONObject doGETJSON = JSONObject.fromObject(doGETRes);
            // log.debug("天润监控返回坐席信息:" + doGETJSON);
            try {
                JSONArray queueArray = doGETJSON.getJSONArray("queueStatus");

                // 变量初始化
                JSONObject queueJson = new JSONObject();
                String qno = "";
                String qname = "";

                JSONObject queueParams = new JSONObject();
                int maxWait = 0;
                int availableCount = 0;
                int idleCount = 0;
                int completed = 0;
                int abandoned = 0;
                int calls = 0;
                int serviceLevel = 0;
                int weight = 0;
                int strategy = 0;
                int queueTimeout = 0;
                int memberTimeout = 0;
                String serviceLevelPerf = "";

                String updateSQL = "";

                // 监控数量统计初始化
                Map<String, Integer> resMap = new HashMap<String, Integer>();
                int inWaitNum = 0;

                // 处理队列成员queueParams
                for (int i = 0; i < queueArray.size(); i++) {
                    queueJson = queueArray.getJSONObject(i);
                    qno = queueJson.getString("qno");
                    qname = queueJson.getString("qname");

                    queueParams = queueJson.getJSONObject("queueParams");
                    maxWait = queueParams.getInt("maxWait");
                    availableCount = queueParams.getInt("availableCount");
                    idleCount = queueParams.getInt("idleCount");
                    completed = queueParams.getInt("completed");
                    abandoned = queueParams.getInt("abandoned");
                    calls = queueParams.getInt("calls");
                    serviceLevel = queueParams.getInt("serviceLevel");
                    serviceLevelPerf = queueParams.getString("serviceLevelPerf");
                    weight = queueParams.getInt("weight");
                    strategy = queueParams.getInt("strategy");
                    queueTimeout = queueParams.getInt("queueTimeout");
                    memberTimeout = queueParams.getInt("memberTimeout");

                    // log.debug("当前监控-队列信息:" + qno + " " + qname);
                    updateSQL = "Replace Into Trc2_Queue_Monitor (Qno, Qname, Maxwait, Availablecount, Idlecount, Completed, Abandoned, Calls, Servicelevel, Servicelevelperf, Weight, Strategy, Queuetimeout, Membertimeout, Update_Time) Values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

                    jt.update(updateSQL, qno, qname, maxWait, availableCount, idleCount, completed, abandoned, calls, serviceLevel, serviceLevelPerf, weight, strategy, queueTimeout, memberTimeout, Update_Time);

                    // 处理坐席成员agentStatus(座席状态，IDLE：空闲；PAUSE：置忙；WRAPUP：整理；CALLING：呼叫中；RINGING：响铃；BUSY：通话)
                    resMap = dealAgentStatus(eliteBean, jt, qno, qname, Update_Time, queueJson);

                    // 处理排队成员queueEntries
                    inWaitNum = dealQueueEntries(eliteBean, jt, qno, qname, Update_Time, queueJson);

                    // 发送多播消息通知坐席端
                    sendWebSocket(jt, qno, qname, resMap.get("inAgentNum"), resMap.get("inBusyNum"), resMap.get("inFreeNum"), resMap.get("inTalkNum"), inWaitNum, resMap.get("inACWNum"), resMap.get("inAUXNum"));


                }

                // 将本次未更新的队列删除
                updateSQL = "Delete From Trc2_Queue_Monitor Where Update_Time != ?";
                jt.update(updateSQL, Update_Time);

                // 将本次未更新的坐席删除
                updateSQL = "Delete From Trc2_Agent_Monitor Where Update_Time != ?";
                jt.update(updateSQL, Update_Time);

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

        } catch (ClientException e) {
            e.printStackTrace();
        } catch (ServerException e) {
            e.printStackTrace();
        }

        return 1;
    }

    // 处理坐席成员agentStatus
    public static Map<String, Integer> dealAgentStatus(EliteBean eliteBean, JdbcTemplate jt, String qno, String qname, String Update_Time, JSONObject queueJson) {

        Map<String, Integer> resMap = new HashMap<String, Integer>();
        resMap.put("inAgentNum", 0);
        resMap.put("inBusyNum", 0);
        resMap.put("inFreeNum", 0);
        resMap.put("inTalkNum", 0);
        resMap.put("inACWNum", 0);
        resMap.put("inAUXNum", 0);

        //log.debug("处理坐席成员agentStatus-队列信息:" + qno + " " + qname + " queueJson:" + queueJson);
        try {
            String updateSQL = "";

            // 初始化变量
            JSONObject agentJson = new JSONObject();
            String cno = "";
            String clientName = "";
            String bindType = "";
            String bindTel = "";
            String customerNumber = "";
            String customerNumberEncrypt = "";
            String pauseType = "";
            String pauseDescription = "";
            String agentStatus = "";
            String agentStatusDetail = "";
            String incomingCallCount = "";
            String queueIncomingCallCount = "";
            String stateDuration = "";
            String loginDuration = "";

            // 定义队列监控数量
            int inBusyNum = 0;
            int inFreeNum = 0;
            int inTalkNum = 0;
            int inACWNum = 0;
            int inAUXNum = 0;

            JSONArray agentArray = queueJson.getJSONArray("agentStatus");
            int inAgentNum = agentArray.size();

            //log.debug("处理坐席成员agentStatus-坐席数量:" + inAgentNum);

            for (int j = 0; j < inAgentNum; j++) {
                agentJson = agentArray.getJSONObject(j);
                cno = KHUtil.GetSFJV(agentJson, "cno");
                clientName = KHUtil.GetSFJV(agentJson, "clientName");
                bindType = KHUtil.GetSFJV(agentJson, "bindType");
                bindTel = KHUtil.GetSFJV(agentJson, "bindTel");
                customerNumber = KHUtil.GetSFJV(agentJson, "customerNumber");
                customerNumberEncrypt = KHUtil.GetSFJV(agentJson, "customerNumberEncrypt");
                pauseType = KHUtil.GetSFJV(agentJson, "pauseType");
                pauseDescription = KHUtil.GetSFJV(agentJson, "pauseDescription");
                agentStatus = KHUtil.GetSFJV(agentJson, "agentStatus");
                agentStatusDetail = KHUtil.GetSFJV(agentJson, "agentStatusDetail");
                incomingCallCount = KHUtil.GetSFJV(agentJson, "incomingCallCount");
                queueIncomingCallCount = KHUtil.GetSFJV(agentJson, "queueIncomingCallCount");
                stateDuration = KHUtil.GetSFJV(agentJson, "stateDuration");
                loginDuration = KHUtil.GetSFJV(agentJson, "loginDuration");

                if (agentStatus == "PAUSE") {
                    inBusyNum++;
                } else if (agentStatus == "IDLE") {
                    inFreeNum++;
                } else if (agentStatus == "BUSY") {
                    inTalkNum++;
                } else if (agentStatus == "WRAPUP") {
                    inACWNum++;
                } else if (agentStatus == "PAUSE") {
                    inAUXNum++;
                }

                updateSQL = "Replace Into Trc2_Agent_Monitor (Cno, Qno, Clientname, Bindtype, Bindtel, Customernumber, Customernumberencrypt, Pausetype, Pausedescription, Agentstatus, Agentstatusdetail, Incomingcallcount, Queueincomingcallcount, Stateduration, Loginduration, Update_Time) Values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

                jt.update(updateSQL, cno, qno, clientName, bindType, bindTel, customerNumber, customerNumberEncrypt, pauseType, pauseDescription, agentStatus, agentStatusDetail, incomingCallCount, queueIncomingCallCount, stateDuration, loginDuration, Update_Time);

            }

            resMap.put("inAgentNum", inAgentNum);
            resMap.put("inBusyNum", inBusyNum);
            resMap.put("inFreeNum", inFreeNum);
            resMap.put("inTalkNum", inTalkNum);
            resMap.put("inACWNum", inACWNum);
            resMap.put("inAUXNum", inAUXNum);

        } catch (Exception e) {
            log.error("处理坐席成员agentStatus-数据处理错误", e);
        }

        //log.debug("处理坐席成员agentStatus-队列信息:" + qno + "/" + qname + " 队列数量统计结果:" + resMap);
        return resMap;

    }

    // 处理排队客户queueEntries
    public static int dealQueueEntries(EliteBean eliteBean, JdbcTemplate jt, String qno, String qname, String Update_Time, JSONObject queueJson) {
        //log.debug("处理排队客户queueEntries-队列信息:" + qno + " " + qname + " queueJson:" + queueJson);
        int inWaitNum = 0;
        try {
            String updateSQL = "";
            JSONObject queueEntriesJson = new JSONObject();

            String uniqueId = "";
            String customerNumberw = "";
            String startTime = "";
            String joinTime = "";
            String waitTime = "";
            String priority = "";
            String overflow = "";
            String position = "";

            JSONArray queueEntriesArray = queueJson.getJSONArray("queueEntries");

            // 循环解析队列中排队的客户
            inWaitNum = queueEntriesArray.size();
            //log.debug("处理排队客户queueEntries-排队数量:" + inWaitNum);

            for (int j = 0; j < inWaitNum; j++) {
                queueEntriesJson = queueEntriesArray.getJSONObject(j);

                uniqueId = KHUtil.GetSFJV(queueEntriesJson, "uniqueId");
                customerNumberw = KHUtil.GetSFJV(queueEntriesJson, "customerNumber");
                startTime = KHUtil.GetSFJV(queueEntriesJson, "startTime");
                joinTime = KHUtil.GetSFJV(queueEntriesJson, "joinTime");
                waitTime = KHUtil.GetSFJV(queueEntriesJson, "waitTime");
                priority = KHUtil.GetSFJV(queueEntriesJson, "priority");
                overflow = KHUtil.GetSFJV(queueEntriesJson, "overflow");
                position = KHUtil.GetSFJV(queueEntriesJson, "position");

                updateSQL = "Replace Into Trc2_Queue_Waiting (Qno, Uniqueid, Customernumber, Starttime, Jointime, Waittime, Priority, Overflow, Position, Update_Time) Values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

                jt.update(updateSQL, qno, uniqueId, customerNumberw, startTime, joinTime, waitTime, priority, overflow, position, Update_Time);

            }

            // 将不在本次结果中的监控数据迁入历史表
            updateSQL = "Insert Into Trc2_Queue_Wait_His (Rec_No, Qno, Uniqueid, Customernumber, Starttime, Jointime, Waittime, Priority, Overflow, Position, Update_Time, His_Time) Select Rec_No, Qno, Uniqueid, Customernumber, Starttime, Jointime, Waittime, Priority, Overflow, Position, Update_Time, Now() From Trc2_Queue_Waiting Where Update_Time != ? And Qno = ?";
            jt.update(updateSQL, Update_Time, qno);

            updateSQL = "Delete From Trc2_Queue_Waiting Where Update_Time != ? And Qno = ?";
            jt.update(updateSQL, Update_Time, qno);

        } catch (Exception e) {
            log.error("处理排队客户queueEntries-数据处理错误", e);
        }
        //log.debug("处理排队客户queueEntries-队列信息:" + qno + "/" + qname + " 排队数量:" + inWaitNum);

        return inWaitNum;

    }

    // 发送队列多播消息
    public static String sendWebSocket(JdbcTemplate jt, String qno, String qname, int inAgentNum, int inBusyNum, int inFreeNum, int inTalkNum, int inWaitNum, int inACWNum, int inAUXNum) {

        // log.debug("发送队列多播消息- Queue:" + qno + " qname:" + qname + " AgentNum:" + inAgentNum + " BusyNum:" + inBusyNum + " FreeNum:" + inFreeNum + " TalkNum:" + inTalkNum + " WaitNum:" + inWaitNum + " ACWNum:" + inACWNum + " AUXNum:" + inAUXNum);

        // 先将数据推送到实时监控
        String EliteMonitorParam = "Queue=" + qno + "&QueueName=" + qname + "&Agent=" + inAgentNum + "&Free=" + inFreeNum + "&Busy=" + inBusyNum + "&ACW=" + inACWNum + "&AUX=" + inAUXNum + "&Wait=" + inWaitNum;

        // 1-获取其他服务器列表
        List serverList = jt.queryForList("Select Concat('http://', Webserverip, ':', Webserverport, '/CTIEliteMonitor/queuestatecallback.jsp?') As Serverapi From Webserverlist");
        for (int j = 0; j < serverList.size(); j++) {
            Map serverMap = serverList.get(j);
            String serverAPIURL = serverMap.get("Serverapi") + EliteMonitorParam;

            // 调用接口通知
            try {
                String sendResult = Util.doHttpGet(serverAPIURL, "UTF-8", 10000, 0);
                //log.debug("发送队列多播消息-通知服务器同步URL:" + serverAPIURL);
            } catch (Exception e) {
                log.error("发送队列多播消息-通知服务器队列结果异常", e);
            }

        }

        // 处理监控数据
        dealDNList(jt, qno, qname, inWaitNum.toString());
    }

    // 状态推送涉及队列处理
    public static String dealDNList(JdbcTemplate jt, String Queue, String QueueName, String Wait) {
        try {

            //log.debug("状态推送涉及队列处理-Queue:" + Queue + " QueueName:" + QueueName + " Wait:" + Wait);


            // 处理主数据
            if (!KHUtil.isNull(Queue)) {
                // 检查当前数据库是否存在 存在更新 不存在新建
                String sql = "Select Count(*) As Count From Dn_List Where Dn = ?";
                List<Map<String, Object>> sqlResult = jt.queryForList(sql, Queue);
                int Countnum = sqlResult.get(0).get("Count");

                if (Countnum <= 0) {
                    String insertSQL = "Insert Into Dn_List (Dn, Type, Monitored, Dnname, Linkname, Wait_Num) Values (?, 3, 1, ?, 'link1', ?)";
                    int num = jt.update(insertSQL, Queue, QueueName, Wait);
                    //log.debug("状态推送涉及队列处理-Dn_List(" + Queue + ") 数量：" + num);
                } else {
                    String insertSQL = "Update Dn_List Set Type = 3, Monitored = 1, Dnname = ?, Linkname = 'link1', Wait_Num = ? Where Dn = ?";
                    int num = jt.update(insertSQL, QueueName, Wait, Queue);
                    //log.debug("状态推送涉及队列处理更新-Dn_List(" + Queue + ") 数量：" + num);

                }

            }

        } catch (Exception e) {
            log.error("状态推送涉及队列处理-数据处理错误", e);
            return "-1";
        }

        return "200";

    }
}